This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

1/11/19 Chapter 5: Data Transformation Setting Up Libraries

rr library(tidyverse) library(nycflights13) library(dplyr)

dplyr overwrites and you need stats::filter() and stats::lag()

rr flights

int for integers dbl stands for doubles, or real numbers chr stands for cahracter vectors, or strings dttm stands fo date-times (a date + time) lgl is logical fctr factors, categorical data dates stands for dates

dplyr basics

pick by values: filter reorder: arrange pick variables: select create new variables from existing existing varaibles: mutate mutate in place: transmute

rr filter(flights, month == 1, day == 1)

Here we filter for Jan 1 flights

To set a variable and print results, run with a parentheses

rr (dec25 <- filter(flights, month == 12, day == 25))

floating point numbers are not good with the == boolean, so instead use the near() function

rr sqrt(2)^2 == 2

[1] FALSE

rr near(sqrt(2)^2, 2)

[1] TRUE

Since the computer uses an approximation fo the calculation, the boolean returns false.

& Intersection (Must be in X and Y) | Union (In X and Y or in just X or in just Y) ! Composite (Not in X)

rr filter(flights, month == 11| month == 12)

We can’t use month == 11 | 12 as that transforms the parameter into a logical True/False Statement. The binary statement is understood as a 0/1 (Remember binary) and thus the statements turns into month == 1 because it is true that 11 union 12 are are contained in one another.

e.g.

rr filter(flights, month == 11|12)

So instead for shorthand you can use

rr filter(flights, month %in% c(11,12))

The c stands for concatenate and creates a vector of numbers to be read by R. The %in% is a dplyr thing that I really don’t know much about.

Missing or unknown values are known as NA don’t try to filter them with logicals Use is.na() unction instead

rr arrange(flights, desc(dep_delay))

Now go on to filtering variables through select

rr select(flights,year, month, day) r select(flights,year:day)

rr select(flights, -(year:day))

There are a number of helper functions you can use within select():

starts_with("abc"): matches names that begin with "abc".

ends_with("xyz"): matches names that end with "xyz".

contains("ijk"): matches names that contain "ijk".

matches("(.)\\1"): selects variables that match a regular expression. This one matches any variables that contain repeated characters. You'll learn more about regular expressions in strings.

num_range("x", 1:3): matches x1, x2 and x3.

rr rename(flights, tail_num = tailnum)

Then we also have hte helper everythin() which can help you move things to the begining of the dataframe

rr select(flights, time_hour, air_time, everything())

Ecercises

rr select(flights, time_hour, time_hour)

Add new variables with mutate

rr flights_sml <- select(flights, year:day, ends_with(), distance, air_time) mutate(flights_sml, gain = dep_delay - arr_delay, speed = distance / air_time * 60)

rr mutate(flights_sml, gain = dep_delay - arr_delay, hours = air_time / 60, gain_per_hour = gain / hours )

to keep only the new variables we use transmute

rr transmute(flights, gain = dep_delay - arr_delay, hours = air_time / 60, gain_per_hour = gain / hours )

useful functions

rr transmute(flights, dep_time, hour = dep_time %/% 100, minute = dep_time %% 100 )

use log(), log2() and log10()

Use log2 cause its easy to interpret

Use lead and lag to find the next and previous value in the vector

rr x <- 1:10 lag(x)

 [1] NA  1  2  3  4  5  6  7  8  9

rr lead(x)

 [1]  2  3  4  5  6  7  8  9 10 NA

Lastly summarise will collapse a data frame into a single row

rr summarise(flights, delay = mean(dep_delay, na.rm = T))

rr by_day <- group_by(flights, year, month, day) summarise(by_day, delay = mean(dep_delay), na.rm = TRUE)

by_dest <- group_by(flights, dest)
delay <- summarise(by_dest, 
                   count = n(),
                   dist = mean(distance, na.rm = TRUE),
                   delay = mean(arr_delay, na.rm = TRUE)
                   )
delay <- filter(delay, count > 20, dest != "HNL")
ggplot(data = delay, mapping = aes(x = dist, y = delay)) +
  geom_point(aes(size = count), alpha = 1/3) + 
  geom_smooth(se = FALSE)

Using a pipe

delays <- flights %>%
  group_by(dest) %>%
  summarise(
    count = n(),
    dist = mean(distance, na.rm = TRUE),
    delay = mean(arr_delay, na.rm = TRUE)
  ) %>%
  filter(count > 20, dest != "HNL")
ggplot(data = delay, mapping = aes(x = dist, y = delay)) +
  geom_point(aes(size = count), alpha = 1/3) + 
  geom_smooth(se = FALSE)

Think of the pipe %>% as a “and Then” na.rm is to remove missing values

Counts

not_cancelled <- flights %>% 
  filter(!is.na(dep_delay), !is.na(arr_delay))
not_cancelled %>% 
  group_by(year, month, day) %>% 
  summarise(mean = mean(dep_delay))

rr delays <- not_cancelled %>% group_by(tailnum) %>% summarise( delay = mean(arr_delay) ) ggplot(data=delays, mapping = aes(x = delay)) + geom_freqpoly(binwidth = 10)

delays <- not_cancelled %>%
  group_by(tailnum) %>%
  summarise( delay = mean(arr_delay, na.rm = T),
             n = n()
             )
ggplot(data = delays, mapping = aes(x = n, y = delay)) +
  geom_point(alpha = 0.1)

library(Lahman)
batting <- as_tibble(Lahman::Batting)
batters <- batting %>%
  group_by(playerID) %>%
  summarise(
    ba = sum(H, na.rm = TRUE) / sum(AB, na.rm = TRUE),
    ab = sum(AB, na.rm = TRUE)
  )
batters %>%
  filter(ba > 100) %>%
  ggplot(mapping = aes(x = ab, y = ba)) +
  geom_point() + 
  geom_smooth(se = FALSE)

Chapter 7 Loading Libraries

library(tidyverse)

Two types of questions that are really important to your research

  1. What type of variation occurs within my variables?
  2. What type of covariation occurs between my variables

Varaible - measuarable thing Value - state of variable when measured observation - set of values made under similar conditions tabular data - observations x variables

Variation - tendency of values to change from measurement to measurement

Visualizing distributions can be used to understand the pattern of variation within the data

LS0tCnRpdGxlOiAiUiBmb3IgRGF0YSBTY2llbmNlcyBmcm9tIENoYXB0ZXIgNSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouIAoKQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkN0cmwrQWx0K0kqLgoKV2hlbiB5b3Ugc2F2ZSB0aGUgbm90ZWJvb2ssIGFuIEhUTUwgZmlsZSBjb250YWluaW5nIHRoZSBjb2RlIGFuZCBvdXRwdXQgd2lsbCBiZSBzYXZlZCBhbG9uZ3NpZGUgaXQgKGNsaWNrIHRoZSAqUHJldmlldyogYnV0dG9uIG9yIHByZXNzICpDdHJsK1NoaWZ0K0sqIHRvIHByZXZpZXcgdGhlIEhUTUwgZmlsZSkuCgpUaGUgcHJldmlldyBzaG93cyB5b3UgYSByZW5kZXJlZCBIVE1MIGNvcHkgb2YgdGhlIGNvbnRlbnRzIG9mIHRoZSBlZGl0b3IuIENvbnNlcXVlbnRseSwgdW5saWtlICpLbml0KiwgKlByZXZpZXcqIGRvZXMgbm90IHJ1biBhbnkgUiBjb2RlIGNodW5rcy4gSW5zdGVhZCwgdGhlIG91dHB1dCBvZiB0aGUgY2h1bmsgd2hlbiBpdCB3YXMgbGFzdCBydW4gaW4gdGhlIGVkaXRvciBpcyBkaXNwbGF5ZWQuCgoxLzExLzE5CkNoYXB0ZXIgNTogRGF0YSBUcmFuc2Zvcm1hdGlvbgpTZXR0aW5nIFVwIExpYnJhcmllcwoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KG55Y2ZsaWdodHMxMykKbGlicmFyeShkcGx5cikKYGBgCgpkcGx5ciBvdmVyd3JpdGVzIGFuZCB5b3UgbmVlZCBzdGF0czo6ZmlsdGVyKCkgYW5kIHN0YXRzOjpsYWcoKQoKYGBge3J9CmZsaWdodHMKYGBgCgppbnQgZm9yIGludGVnZXJzCmRibCBzdGFuZHMgZm9yIGRvdWJsZXMsIG9yIHJlYWwgbnVtYmVycwpjaHIgc3RhbmRzIGZvciBjYWhyYWN0ZXIgdmVjdG9ycywgb3Igc3RyaW5ncwpkdHRtIHN0YW5kcyBmbyBkYXRlLXRpbWVzIChhIGRhdGUgKyB0aW1lKQpsZ2wgaXMgbG9naWNhbCAKZmN0ciBmYWN0b3JzLCBjYXRlZ29yaWNhbCBkYXRhCmRhdGVzIHN0YW5kcyBmb3IgZGF0ZXMKCgpkcGx5ciBiYXNpY3MKCnBpY2sgYnkgdmFsdWVzOiBmaWx0ZXIKcmVvcmRlcjogYXJyYW5nZQpwaWNrIHZhcmlhYmxlczogc2VsZWN0CmNyZWF0ZSBuZXcgdmFyaWFibGVzIGZyb20gZXhpc3RpbmcgZXhpc3RpbmcgdmFyYWlibGVzOiBtdXRhdGUKbXV0YXRlIGluIHBsYWNlOiB0cmFuc211dGUKCmBgYHtyfQpmaWx0ZXIoZmxpZ2h0cywgbW9udGggPT0gMSwgZGF5ID09IDEpCmBgYApIZXJlIHdlIGZpbHRlciBmb3IgSmFuIDEgZmxpZ2h0cwoKVG8gc2V0IGEgdmFyaWFibGUgYW5kIHByaW50IHJlc3VsdHMsIHJ1biB3aXRoIGEgcGFyZW50aGVzZXMKCmBgYHtyfQooZGVjMjUgPC0gZmlsdGVyKGZsaWdodHMsIG1vbnRoID09IDEyLCBkYXkgPT0gMjUpKQpgYGAKCmZsb2F0aW5nIHBvaW50IG51bWJlcnMgYXJlIG5vdCBnb29kIHdpdGggdGhlICA9PSBib29sZWFuLCBzbyBpbnN0ZWFkIHVzZSB0aGUgbmVhcigpIGZ1bmN0aW9uCgpgYGB7cn0Kc3FydCgyKV4yID09IDIKbmVhcihzcXJ0KDIpXjIsIDIpCmBgYAoKU2luY2UgdGhlIGNvbXB1dGVyIHVzZXMgYW4gYXBwcm94aW1hdGlvbiBmbyB0aGUgY2FsY3VsYXRpb24sIHRoZSBib29sZWFuIHJldHVybnMgZmFsc2UuIAoKJiBJbnRlcnNlY3Rpb24gKE11c3QgYmUgaW4gWCBhbmQgWSkKfCBVbmlvbiAoSW4gWCBhbmQgWSBvciBpbiBqdXN0IFggb3IgaW4ganVzdCBZKQohIENvbXBvc2l0ZSAoTm90IGluIFgpCgpgYGB7cn0KZmlsdGVyKGZsaWdodHMsIG1vbnRoID09IDExfCBtb250aCA9PSAxMikKYGBgCgpXZSBjYW4ndCB1c2UgbW9udGggPT0gMTEgfCAxMiBhcyB0aGF0IHRyYW5zZm9ybXMgdGhlIHBhcmFtZXRlciBpbnRvIGEgbG9naWNhbCBUcnVlL0ZhbHNlIFN0YXRlbWVudC4gVGhlIGJpbmFyeSBzdGF0ZW1lbnQgaXMgdW5kZXJzdG9vZCBhcyBhIDAvMSAoUmVtZW1iZXIgYmluYXJ5KSBhbmQgdGh1cyB0aGUgc3RhdGVtZW50cyB0dXJucyBpbnRvIG1vbnRoID09IDEgYmVjYXVzZSBpdCBpcyB0cnVlIHRoYXQgMTEgdW5pb24gMTIgYXJlIGFyZSBjb250YWluZWQgaW4gb25lIGFub3RoZXIuCgplLmcuCmBgYHtyfQpmaWx0ZXIoZmxpZ2h0cywgbW9udGggPT0gMTF8MTIpCmBgYApTbyBpbnN0ZWFkIGZvciBzaG9ydGhhbmQgeW91IGNhbiB1c2UKYGBge3J9CmZpbHRlcihmbGlnaHRzLCBtb250aCAlaW4lIGMoMTEsMTIpKQpgYGAKVGhlIGMgc3RhbmRzIGZvciBjb25jYXRlbmF0ZSBhbmQgY3JlYXRlcyBhIHZlY3RvciBvZiBudW1iZXJzIHRvIGJlIHJlYWQgYnkgUi4gVGhlICVpbiUgaXMgYSBkcGx5ciB0aGluZyB0aGF0IEkgcmVhbGx5IGRvbid0IGtub3cgbXVjaCBhYm91dC4KCk1pc3Npbmcgb3IgdW5rbm93biB2YWx1ZXMgYXJlIGtub3duIGFzIE5BCmRvbid0IHRyeSB0byBmaWx0ZXIgdGhlbSB3aXRoIGxvZ2ljYWxzClVzZSBpcy5uYSgpIHVuY3Rpb24gaW5zdGVhZAoKYGBge3J9CmFycmFuZ2UoZmxpZ2h0cywgaXMubmEoKSkKCmBgYAoKTm93IGdvIG9uIHRvIGZpbHRlcmluZyB2YXJpYWJsZXMgdGhyb3VnaCBzZWxlY3QKCmBgYHtyfQpzZWxlY3QoZmxpZ2h0cyx5ZWFyLCBtb250aCwgZGF5KQpzZWxlY3QoZmxpZ2h0cyx5ZWFyOmRheSkKc2VsZWN0KGZsaWdodHMsIC0oeWVhcjpkYXkpKQpgYGAKClRoZXJlIGFyZSBhIG51bWJlciBvZiBoZWxwZXIgZnVuY3Rpb25zIHlvdSBjYW4gdXNlIHdpdGhpbiBzZWxlY3QoKToKCiAgICBzdGFydHNfd2l0aCgiYWJjIik6IG1hdGNoZXMgbmFtZXMgdGhhdCBiZWdpbiB3aXRoICJhYmMiLgoKICAgIGVuZHNfd2l0aCgieHl6Iik6IG1hdGNoZXMgbmFtZXMgdGhhdCBlbmQgd2l0aCAieHl6Ii4KCiAgICBjb250YWlucygiaWprIik6IG1hdGNoZXMgbmFtZXMgdGhhdCBjb250YWluICJpamsiLgoKICAgIG1hdGNoZXMoIiguKVxcMSIpOiBzZWxlY3RzIHZhcmlhYmxlcyB0aGF0IG1hdGNoIGEgcmVndWxhciBleHByZXNzaW9uLiBUaGlzIG9uZSBtYXRjaGVzIGFueSB2YXJpYWJsZXMgdGhhdCBjb250YWluIHJlcGVhdGVkIGNoYXJhY3RlcnMuIFlvdSdsbCBsZWFybiBtb3JlIGFib3V0IHJlZ3VsYXIgZXhwcmVzc2lvbnMgaW4gc3RyaW5ncy4KCiAgICBudW1fcmFuZ2UoIngiLCAxOjMpOiBtYXRjaGVzIHgxLCB4MiBhbmQgeDMuCgpgYGB7cn0KcmVuYW1lKGZsaWdodHMsIHRhaWxfbnVtID0gdGFpbG51bSkKYGBgCgpUaGVuIHdlIGFsc28gaGF2ZSBodGUgaGVscGVyIGV2ZXJ5dGhpbigpIHdoaWNoIGNhbiBoZWxwIHlvdSBtb3ZlIHRoaW5ncyB0byB0aGUgYmVnaW5pbmcgb2YgdGhlIGRhdGFmcmFtZQoKYGBge3J9CnNlbGVjdChmbGlnaHRzLCB0aW1lX2hvdXIsIGFpcl90aW1lLCBldmVyeXRoaW5nKCkpCmBgYAoKRWNlcmNpc2VzCmBgYHtyfQpzZWxlY3QoZmxpZ2h0cywgdGltZV9ob3VyLCB0aW1lX2hvdXIpCmBgYApBZGQgbmV3IHZhcmlhYmxlcyB3aXRoIG11dGF0ZQoKYGBge3J9CmZsaWdodHNfc21sIDwtIHNlbGVjdChmbGlnaHRzLCB5ZWFyOmRheSwgZW5kc193aXRoKCJkZWxheSIpLCBkaXN0YW5jZSwgYWlyX3RpbWUpCgptdXRhdGUoZmxpZ2h0c19zbWwsIGdhaW4gPSBkZXBfZGVsYXkgLSBhcnJfZGVsYXksCiAgICAgICBzcGVlZCA9IGRpc3RhbmNlIC8gYWlyX3RpbWUgKiA2MCkKYGBgCmBgYHtyfQptdXRhdGUoZmxpZ2h0c19zbWwsCiAgICAgICBnYWluID0gZGVwX2RlbGF5IC0gYXJyX2RlbGF5LAogICAgICAgaG91cnMgPSBhaXJfdGltZSAvIDYwLAogICAgICAgZ2Fpbl9wZXJfaG91ciA9IGdhaW4gLyBob3VycwogICAgICAgKQpgYGAKCnRvIGtlZXAgb25seSB0aGUgbmV3IHZhcmlhYmxlcyB3ZSB1c2UgdHJhbnNtdXRlCmBgYHtyfQp0cmFuc211dGUoZmxpZ2h0cywgCiAgICAgICAgICBnYWluID0gZGVwX2RlbGF5IC0gYXJyX2RlbGF5LAogICAgICAgICAgaG91cnMgPSBhaXJfdGltZSAvIDYwLAogICAgICAgICAgZ2Fpbl9wZXJfaG91ciA9IGdhaW4gLyBob3VycwogICAgICAgICAgKQpgYGAKCnVzZWZ1bCBmdW5jdGlvbnMKYGBge3J9CnRyYW5zbXV0ZShmbGlnaHRzLAogICAgICAgICAgZGVwX3RpbWUsCiAgICAgICAgICBob3VyID0gZGVwX3RpbWUgJS8lIDEwMCwKICAgICAgICAgIG1pbnV0ZSA9IGRlcF90aW1lICUlIDEwMAogICAgICAgICAgKQpgYGAKdXNlIGxvZygpLCBsb2cyKCkgYW5kIGxvZzEwKCkKClVzZSBsb2cyIGNhdXNlIGl0cyBlYXN5IHRvIGludGVycHJldAoKVXNlIGxlYWQgYW5kIGxhZyB0byBmaW5kIHRoZSBuZXh0IGFuZCBwcmV2aW91cyB2YWx1ZSBpbiB0aGUgdmVjdG9yCgpgYGB7cn0KeCA8LSAxOjEwCmxhZyh4KQpsZWFkKHgpCmBgYAogTGFzdGx5IHN1bW1hcmlzZSB3aWxsIGNvbGxhcHNlIGEgZGF0YSBmcmFtZSBpbnRvIGEgc2luZ2xlIHJvdwpgYGB7cn0Kc3VtbWFyaXNlKGZsaWdodHMsIGRlbGF5ID0gbWVhbihkZXBfZGVsYXksIG5hLnJtID0gVCkpCmBgYAogCmBgYHtyfQpieV9kYXkgPC0gZ3JvdXBfYnkoZmxpZ2h0cywgeWVhciwgbW9udGgsIGRheSkKc3VtbWFyaXNlKGJ5X2RheSwgZGVsYXkgPSBtZWFuKGRlcF9kZWxheSksIG5hLnJtID0gVFJVRSkKYGBgCmBgYHtyfQpieV9kZXN0IDwtIGdyb3VwX2J5KGZsaWdodHMsIGRlc3QpCmRlbGF5IDwtIHN1bW1hcmlzZShieV9kZXN0LCAKICAgICAgICAgICAgICAgICAgIGNvdW50ID0gbigpLAogICAgICAgICAgICAgICAgICAgZGlzdCA9IG1lYW4oZGlzdGFuY2UsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgICAgICAgICBkZWxheSA9IG1lYW4oYXJyX2RlbGF5LCBuYS5ybSA9IFRSVUUpCiAgICAgICAgICAgICAgICAgICApCmRlbGF5IDwtIGZpbHRlcihkZWxheSwgY291bnQgPiAyMCwgZGVzdCAhPSAiSE5MIikKZ2dwbG90KGRhdGEgPSBkZWxheSwgbWFwcGluZyA9IGFlcyh4ID0gZGlzdCwgeSA9IGRlbGF5KSkgKwogIGdlb21fcG9pbnQoYWVzKHNpemUgPSBjb3VudCksIGFscGhhID0gMS8zKSArIAogIGdlb21fc21vb3RoKHNlID0gRkFMU0UpCmBgYAoKVXNpbmcgYSBwaXBlCmBgYHtyfQpkZWxheXMgPC0gZmxpZ2h0cyAlPiUKICBncm91cF9ieShkZXN0KSAlPiUKICBzdW1tYXJpc2UoCiAgICBjb3VudCA9IG4oKSwKICAgIGRpc3QgPSBtZWFuKGRpc3RhbmNlLCBuYS5ybSA9IFRSVUUpLAogICAgZGVsYXkgPSBtZWFuKGFycl9kZWxheSwgbmEucm0gPSBUUlVFKQogICkgJT4lCiAgZmlsdGVyKGNvdW50ID4gMjAsIGRlc3QgIT0gIkhOTCIpCmdncGxvdChkYXRhID0gZGVsYXksIG1hcHBpbmcgPSBhZXMoeCA9IGRpc3QsIHkgPSBkZWxheSkpICsKICBnZW9tX3BvaW50KGFlcyhzaXplID0gY291bnQpLCBhbHBoYSA9IDEvMykgKyAKICBnZW9tX3Ntb290aChzZSA9IEZBTFNFKQpgYGAKCgpUaGluayBvZiB0aGUgcGlwZSAlPiUgYXMgYSAiYW5kIFRoZW4iCm5hLnJtIGlzIHRvIHJlbW92ZSBtaXNzaW5nIHZhbHVlcwoKQ291bnRzIApgYGB7cn0Kbm90X2NhbmNlbGxlZCA8LSBmbGlnaHRzICU+JSAKICBmaWx0ZXIoIWlzLm5hKGRlcF9kZWxheSksICFpcy5uYShhcnJfZGVsYXkpKQoKbm90X2NhbmNlbGxlZCAlPiUgCiAgZ3JvdXBfYnkoeWVhciwgbW9udGgsIGRheSkgJT4lIAogIHN1bW1hcmlzZShtZWFuID0gbWVhbihkZXBfZGVsYXkpKQpgYGAKCmBgYHtyfQpkZWxheXMgPC0gIG5vdF9jYW5jZWxsZWQgJT4lIAogIGdyb3VwX2J5KHRhaWxudW0pICU+JQogIHN1bW1hcmlzZSgKICAgIGRlbGF5ID0gbWVhbihhcnJfZGVsYXkpCiAgKQoKZ2dwbG90KGRhdGE9ZGVsYXlzLCBtYXBwaW5nID0gYWVzKHggPSBkZWxheSkpICsgCiAgZ2VvbV9mcmVxcG9seShiaW53aWR0aCA9IDEwKQpgYGAKYGBge3J9CmRlbGF5cyA8LSBub3RfY2FuY2VsbGVkICU+JQogIGdyb3VwX2J5KHRhaWxudW0pICU+JQogIHN1bW1hcmlzZSggZGVsYXkgPSBtZWFuKGFycl9kZWxheSwgbmEucm0gPSBUKSwKICAgICAgICAgICAgIG4gPSBuKCkKICAgICAgICAgICAgICkKZ2dwbG90KGRhdGEgPSBkZWxheXMsIG1hcHBpbmcgPSBhZXMoeCA9IG4sIHkgPSBkZWxheSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC4xKQpgYGAKYGBge3J9CmRlbGF5cyAlPiUKICBmaWx0ZXIobiA+IDI1KSAlPiUKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gbiwgeSA9IGRlbGF5KSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjEpCmBgYAoKYGBge3J9CmxpYnJhcnkoTGFobWFuKQpiYXR0aW5nIDwtIGFzX3RpYmJsZShMYWhtYW46OkJhdHRpbmcpCgpiYXR0ZXJzIDwtIGJhdHRpbmcgJT4lCiAgZ3JvdXBfYnkocGxheWVySUQpICU+JQogIHN1bW1hcmlzZSgKICAgIGJhID0gc3VtKEgsIG5hLnJtID0gVFJVRSkgLyBzdW0oQUIsIG5hLnJtID0gVFJVRSksCiAgICBhYiA9IHN1bShBQiwgbmEucm0gPSBUUlVFKQogICkKCmJhdHRlcnMgJT4lCiAgZmlsdGVyKGJhID4gMTAwKSAlPiUKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gYWIsIHkgPSBiYSkpICsKICBnZW9tX3BvaW50KCkgKyAKICBnZW9tX3Ntb290aChzZSA9IEZBTFNFKQpgYGAKCkNoYXB0ZXIgNwpMb2FkaW5nIExpYnJhcmllcwpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKVHdvIHR5cGVzIG9mIHF1ZXN0aW9ucyB0aGF0IGFyZSByZWFsbHkgaW1wb3J0YW50IHRvIHlvdXIgcmVzZWFyY2gKCjEuIFdoYXQgdHlwZSBvZiB2YXJpYXRpb24gb2NjdXJzIHdpdGhpbiBteSB2YXJpYWJsZXM/CjIuIFdoYXQgdHlwZSBvZiBjb3ZhcmlhdGlvbiBvY2N1cnMgYmV0d2VlbiBteSB2YXJpYWJsZXMKClZhcmFpYmxlIC0gbWVhc3VhcmFibGUgdGhpbmcKVmFsdWUgLSBzdGF0ZSBvZiB2YXJpYWJsZSB3aGVuIG1lYXN1cmVkCm9ic2VydmF0aW9uIC0gc2V0IG9mIHZhbHVlcyBtYWRlIHVuZGVyIHNpbWlsYXIgY29uZGl0aW9ucwp0YWJ1bGFyIGRhdGEgLSBvYnNlcnZhdGlvbnMgeCB2YXJpYWJsZXMgCgpWYXJpYXRpb24gLSB0ZW5kZW5jeSBvZiB2YWx1ZXMgdG8gY2hhbmdlIGZyb20gbWVhc3VyZW1lbnQgdG8gbWVhc3VyZW1lbnQKClZpc3VhbGl6aW5nIGRpc3RyaWJ1dGlvbnMgY2FuIGJlIHVzZWQgdG8gdW5kZXJzdGFuZCB0aGUgcGF0dGVybiBvZiB2YXJpYXRpb24gd2l0aGluIHRoZSBkYXRhCgo=